#region Declaration of Namespace

/// <Summary>
/// Declaration of Namespace
/// </summary>
using System;
using System.IO;
using System.Xml;
using System.Diagnostics;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Runtime.Serialization.Formatters.Binary;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Publishing;
using Microsoft.Office.RecordsManagement.PolicyFeatures;
using Microsoft.Office.RecordsManagement.InformationPolicy;

#endregion

#region namespace SPConfigurator

namespace SPConfigurator
{
    #region class SPConfigurator : SPFeatureReceiver
    /// <summary>
    /// SPConfigurator
    /// </summary>
    [Guid("4e0d8d63-44c7-4b76-a832-988d3df30c98")]
    public class SPConfigurator : SPFeatureReceiver
    {
        #region Constants

        const string TEMPVAR = "TEMP";
        const string LogTextPath = @"SPConfiguratorLog.txt";

        #endregion

        #region Log File

        private static void LogToTempFolder(string toLog)
        {
            string path = Environment.GetEnvironmentVariable(TEMPVAR) + LogTextPath;
            using (StreamWriter sw = File.CreateText(path))
            {
                sw.WriteLine(toLog + ": " + DateTime.Now.ToLongTimeString());
                sw.Flush();
            }
        }

        #endregion

        #region Commented this Log To Event Log

        /// <summary>
        /// LogToEventLog
        /// </summary>
        /// <param name="toLog"></param>
        //private static void LogToEventLog(string toLog)
        //{
        //    sSource = "SPConfigurator";
        //    sLog = "Application";
        //    sEvent = "Sample Event";
        //    if (!EventLog.SourceExists(sSource))
        //    {
        //        EventLog.CreateEventSource(sSource, sLog);
        //    }
        //    EventLog.WriteEntry(sSource, toLog, EventLogEntryType.Information);
        //}

        #endregion

        #region Feature Activated

        /// <summary>
        /// FeatureActivated
        /// </summary>
        /// <param name="properties"></param>
        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            AppSettingsModifier appSettings = new AppSettingsModifier();
            appSettings.LoadSPSiteWithSDP(properties);
        }

        #endregion

        #region Feature Installed

        /// <summary>
        /// FeatureInstalled
        /// </summary>
        /// <param name="properties"></param>
        public override void FeatureInstalled(SPFeatureReceiverProperties properties)
        {
        }

        #endregion

        #region Feature Deactivating

        /// <summary>
        /// FeatureDeactivating
        /// </summary>
        /// <param name="properties"></param>
        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            AppSettingsModifier appSettings = new AppSettingsModifier();
            appSettings.RetractSettings(properties);
        }

        #endregion

        #region Feature Uninstalling

        /// <summary>
        /// FeatureUninstalling
        /// </summary>
        /// <param name="properties"></param>
        public override void FeatureUninstalling(SPFeatureReceiverProperties properties)
        {
        }

        #endregion

        public class AppSettingsModifier
        {
            #region AppSettingsModifier declaration

            private const string XMLCONFIGFILE = @"\Config\AppConfig.xml";
            private const string XMLRETRACTCONFIGFILE = @"\Config\RetractAppConfig.bin";
            private XmlDocument xmlDoc = new XmlDocument();
            private SPSite site;
            private SPListItem SPListItem;
            private SPWeb web;
            PublishingWeb publishingWeb;
            private SPListCollection lists;
            private SPContentTypeCollection contentypes;
            SPAudit siteAudit;
            private AppSettingsContainer AppSettings, ExistingAppSettingsBeforeSDP, CurrentAppSettingsAfterSDP;

            #endregion

            #region Constructor: AppSettingsModifier

            /// <summary>
            /// Constructor: AppSettingsModifier
            /// </summary>
            public AppSettingsModifier()
            {
            }
            #endregion

            #region Load Existing AppSettings From SPSite

            /// <summary>
            /// LoadExistingAppSettingsFromSPSite: This method is to load/save the any previous settings done in MOSS/WSS site settings to AppSettings 
            /// in order to reset them if the newly applied solution is retracted/removed/deleted/deactivated.
            /// </summary>
            /// <param name="properties">SPFeatureReceiverProperties</param>
            /// <param name="site">SPSite</param>
            /// <returns>AppSettingsBeforeSDP</returns>
            private AppSettingsContainer LoadExistingAppSettingsFromSPSite(SPFeatureReceiverProperties properties, SPSite site)
            {
                #region Load Existing App Settings from SPSite to ExistingAppSettingsBeforeSDP container

                ExistingAppSettingsBeforeSDP = new AppSettingsContainer();

                //List<ExpirationPolicy> ExpirationPolicies = new List<ExpirationPolicy>();
                List<ApplyMasterPage> ApplyMasterPages = new List<ApplyMasterPage>();
                //AuditControls AuditControl = new AuditControls();
                //List<ListContentTypeManagement> ListSettings = new List<ListContentTypeManagement>();

                //ExpirationPolicies 
                //if (AppSettings.ExpirationPolicies != null)
                //{
                //}

                //MasterPages
                if (AppSettings.ApplyMasterPages != null)
                {
                    ApplyMasterPages = new List<ApplyMasterPage>();
                    foreach (ApplyMasterPage masterPage in AppSettings.ApplyMasterPages)
                    {
                        ApplyMasterPage masterPageForRetract = new ApplyMasterPage();
                        switch (masterPage.MasterPageType)
                        {
                            case MasterPageType.RegularMasterPage:
                                masterPageForRetract.Name = web.MasterUrl;
                                masterPageForRetract.MasterPageType = MasterPageType.RegularMasterPage;
                                break;

                            case MasterPageType.SystemMasterPage:
                                masterPageForRetract.Name = web.CustomMasterUrl;
                                masterPageForRetract.MasterPageType = MasterPageType.SystemMasterPage;
                                break;
                        }
                        ApplyMasterPages.Add(masterPageForRetract);
                    }
                }
                //AuditControl:
                //if (AppSettings.AuditControl != null)
                //{
                //    siteAudit = site.Audit;

                //    if (!AuditControl.CheckingInOut.HasValue)
                //    {
                //        AuditControl.CheckingInOut = ((siteAudit.AuditFlags & SPAuditMaskType.CheckIn) == SPAuditMaskType.CheckIn) && ((siteAudit.AuditFlags & SPAuditMaskType.CheckOut) == SPAuditMaskType.CheckOut);
                //    }
                //    if (!AuditControl.DeletingRestoring.HasValue)
                //    {
                //        AuditControl.DeletingRestoring = ((siteAudit.AuditFlags & SPAuditMaskType.Delete) == SPAuditMaskType.Delete) && ((siteAudit.AuditFlags & SPAuditMaskType.Undelete) == SPAuditMaskType.Undelete);
                //    }
                //    if (!AuditControl.EditingItems.HasValue)
                //    {
                //        AuditControl.EditingItems = ((siteAudit.AuditFlags & SPAuditMaskType.Update) == SPAuditMaskType.Update);
                //    }
                //    if (!AuditControl.EditingUsersPermissions.HasValue)
                //    {
                //        AuditControl.EditingUsersPermissions = ((siteAudit.AuditFlags & SPAuditMaskType.SecurityChange) == SPAuditMaskType.SecurityChange);
                //    }
                //    if (!AuditControl.EditingContentTypes.HasValue)
                //    {
                //        AuditControl.EditingContentTypes = ((siteAudit.AuditFlags & SPAuditMaskType.SchemaChange) == SPAuditMaskType.SchemaChange) && ((siteAudit.AuditFlags & SPAuditMaskType.ProfileChange) == SPAuditMaskType.ProfileChange);
                //    }
                //    if (!AuditControl.MovingCopying.HasValue)
                //    {
                //        AuditControl.MovingCopying = ((siteAudit.AuditFlags & SPAuditMaskType.Move) == SPAuditMaskType.Move) && ((siteAudit.AuditFlags & SPAuditMaskType.Copy) == SPAuditMaskType.Copy);
                //    }
                //    if (!AuditControl.OpeningDownloadingDocuments.HasValue)
                //    {
                //        AuditControl.OpeningDownloadingDocuments = ((siteAudit.AuditFlags & SPAuditMaskType.View) == SPAuditMaskType.View);
                //    }
                //    if (!AuditControl.SearchingSiteContent.HasValue)
                //    {
                //        AuditControl.SearchingSiteContent = ((siteAudit.AuditFlags & SPAuditMaskType.Search) == SPAuditMaskType.Search);
                //    }
                //}

                ////ListSettings:
                //if (AppSettings.ListSettings != null)
                //{
                //    ListContentTypeManagement listForRetract;
                //    foreach (ListContentTypeManagement list in AppSettings.ListSettings)
                //    {
                //        listForRetract = new ListContentTypeManagement();
                //        try
                //        {
                //            SPList Spl = (SPList)this.lists[list.Name];                                
                //            listForRetract.AllowContentTypeManagement = Spl.ContentTypesEnabled;
                //            listForRetract.Name = list.Name;
                //        }
                //        catch (Exception ex)
                //        {
                //            SPConfigurator.LogToTempFolder(e.Message);
                //        }
                //        ListSettings.Add(listForRetract);
                //    }
                //}

                //ExistingAppSettingsBeforeSDP.ExpirationPolicies = ExpirationPolicies;
                ExistingAppSettingsBeforeSDP.ApplyMasterPages = ApplyMasterPages;
                //ExistingAppSettingsBeforeSDP.AuditControl = AuditControl;
                //ExistingAppSettingsBeforeSDP.ListSettings = ListSettings;

                #endregion

                return ExistingAppSettingsBeforeSDP;
            }

            #endregion

            #region Load Current AppSettings From SPSite

            /// <summary>
            /// LoadCurrentAppSettingsFromSPSite :  This method loads the current settings of the site
            /// </summary>
            /// <param name="properties"></param>
            /// <param name="site"></param>
            /// <returns></returns>
            private AppSettingsContainer LoadCurrentAppSettingsFromSPSite(SPFeatureReceiverProperties properties, SPSite site)
            {
                #region Load Current App Settings from SPSite to CurrentAppSettingsAfterSDP container
                CurrentAppSettingsAfterSDP = new AppSettingsContainer();

                List<ExpirationPolicy> ExpirationPolicies = new List<ExpirationPolicy>();
                List<ApplyMasterPage> ApplyMasterPages = new List<ApplyMasterPage>();
                AuditControls AuditControl = new AuditControls();
                List<ListContentTypeManagement> ListSettings = new List<ListContentTypeManagement>();

                //ExpirationPolicies //TODO: will be implemented later
                if (AppSettings.ExpirationPolicies != null)
                {
                }

                //MasterPages
                if (AppSettings.ApplyMasterPages != null)
                {
                    ApplyMasterPages = new List<ApplyMasterPage>();
                    foreach (ApplyMasterPage masterPage in AppSettings.ApplyMasterPages)
                    {
                        ApplyMasterPage masterPageForRetract = new ApplyMasterPage();
                        switch (masterPage.MasterPageType)
                        {
                            case MasterPageType.RegularMasterPage:
                                masterPageForRetract.Name = web.MasterUrl;
                                masterPageForRetract.MasterPageType = MasterPageType.RegularMasterPage;
                                break;

                            case MasterPageType.SystemMasterPage:
                                masterPageForRetract.Name = web.CustomMasterUrl;
                                masterPageForRetract.MasterPageType = MasterPageType.SystemMasterPage;
                                break;
                        }
                        ApplyMasterPages.Add(masterPageForRetract);
                    }
                }
                //AuditControl:
                if (AppSettings.AuditControl != null)
                {
                    siteAudit = site.Audit;

                    if (!AuditControl.CheckingInOut.HasValue)
                    {
                        AuditControl.CheckingInOut = ((siteAudit.AuditFlags & SPAuditMaskType.CheckIn) == SPAuditMaskType.CheckIn) && ((siteAudit.AuditFlags & SPAuditMaskType.CheckOut) == SPAuditMaskType.CheckOut);
                    }
                    if (!AuditControl.DeletingRestoring.HasValue)
                    {
                        AuditControl.DeletingRestoring = ((siteAudit.AuditFlags & SPAuditMaskType.Delete) == SPAuditMaskType.Delete) && ((siteAudit.AuditFlags & SPAuditMaskType.Undelete) == SPAuditMaskType.Undelete);
                    }
                    if (!AuditControl.EditingItems.HasValue)
                    {
                        AuditControl.EditingItems = ((siteAudit.AuditFlags & SPAuditMaskType.Update) == SPAuditMaskType.Update);
                    }
                    if (!AuditControl.EditingUsersPermissions.HasValue)
                    {
                        AuditControl.EditingUsersPermissions = ((siteAudit.AuditFlags & SPAuditMaskType.SecurityChange) == SPAuditMaskType.SecurityChange);
                    }
                    if (!AuditControl.EditingContentTypes.HasValue)
                    {
                        AuditControl.EditingContentTypes = ((siteAudit.AuditFlags & SPAuditMaskType.SchemaChange) == SPAuditMaskType.SchemaChange) && ((siteAudit.AuditFlags & SPAuditMaskType.ProfileChange) == SPAuditMaskType.ProfileChange);
                    }
                    if (!AuditControl.MovingCopying.HasValue)
                    {
                        AuditControl.MovingCopying = ((siteAudit.AuditFlags & SPAuditMaskType.Move) == SPAuditMaskType.Move) && ((siteAudit.AuditFlags & SPAuditMaskType.Copy) == SPAuditMaskType.Copy);
                    }
                    if (!AuditControl.OpeningDownloadingDocuments.HasValue)
                    {
                        AuditControl.OpeningDownloadingDocuments = ((siteAudit.AuditFlags & SPAuditMaskType.View) == SPAuditMaskType.View);
                    }
                    if (!AuditControl.SearchingSiteContent.HasValue)
                    {
                        AuditControl.SearchingSiteContent = ((siteAudit.AuditFlags & SPAuditMaskType.Search) == SPAuditMaskType.Search);
                    }
                }

                //ListSettings:
                if (AppSettings.ListSettings != null)
                {
                    ListContentTypeManagement listForRetract;
                    foreach (ListContentTypeManagement list in AppSettings.ListSettings)
                    {
                        listForRetract = new ListContentTypeManagement();
                        try
                        {
                            SPList spl = (SPList)lists[list.Name];
                            listForRetract.AllowContentTypeManagement = spl.ContentTypesEnabled;
                            listForRetract.Name = list.Name;
                        }
                        catch (Exception ex)
                        {
                            SPConfigurator.LogToTempFolder(ex.Message);
                        }
                        ListSettings.Add(listForRetract);
                    }
                }

                CurrentAppSettingsAfterSDP.ExpirationPolicies = ExpirationPolicies;
                CurrentAppSettingsAfterSDP.ApplyMasterPages = ApplyMasterPages;
                CurrentAppSettingsAfterSDP.AuditControl = AuditControl;
                CurrentAppSettingsAfterSDP.ListSettings = ListSettings;

                #endregion

                return CurrentAppSettingsAfterSDP;
            }
            #endregion

            #region Load Settings From AppConfig
            /// <summary>
            /// LoadSettingsFromAppConfig: This method is to load/fetch the settings defined in the appconfig.xml 
            /// by the user to the Appsettings object
            /// This method is called/invoked from "LoadSettings" method after the "Initweb" method is executed.
            /// </summary>
            /// <param name="properties">SPFeatureReceiverProperties</param>
            /// <returns>AppSettingsContainer</returns>
            private AppSettingsContainer LoadSettingsFromAppConfig(SPFeatureReceiverProperties properties)
            {
                XmlElement xmlRoot;
                AppSettingsContainer AppSettings;
                
                #region Load All the Settings from XML to AppSettings Object

                // Load settings from the xml
                xmlDoc.Load(properties.Definition.RootDirectory + AppSettingsModifier.XMLCONFIGFILE);
                AppSettings = new AppSettingsContainer();
                //Parse xml and populate AppSettings
                xmlRoot = xmlDoc.DocumentElement;
                List<Title> WebTitles = new List<Title>();
                List<ExpirationPolicy> ExpirationPolicies = new List<ExpirationPolicy>();
                List<ApplyMasterPage> ApplyMasterPages = new List<ApplyMasterPage>();
                AuditControls AuditControl = new AuditControls();
                List<ListContentTypeManagement> ListSettings = new List<ListContentTypeManagement>();

                foreach (XmlNode xmlConfigNode in xmlRoot.ChildNodes)
                {
                    switch (xmlConfigNode.Name)
                    {
                        //Collecting WebTitles.
                        case "WebTitles":

                            foreach (XmlElement WebTitle in xmlConfigNode.ChildNodes)
                            {
                                Title T = new Title();
                                //ListContentTypeManagement ListEntry = new ListContentTypeManagement();
                                T.Name = WebTitle.GetAttribute("Name");
                                T.Site = WebTitle.GetAttribute("Site");
                                WebTitles.Add(T);
                            }
                            AppSettings.WebTitles = WebTitles;
                            break;

                        //Collecting expiration policies.
                        case "ExpirationPolicies":

                            foreach (XmlElement ExpirationPolicy in xmlConfigNode.ChildNodes)
                            {
                                ExpirationPolicy exppolicy = new ExpirationPolicy();
                                //ListContentTypeManagement ListEntry = new ListContentTypeManagement();
                                exppolicy.Type = ExpirationPolicy.GetAttribute("Type");
                                exppolicy.Name = ExpirationPolicy.GetAttribute("Name");
                                exppolicy.Policy = ExpirationPolicy.GetAttribute("Policy");
                                ExpirationPolicies.Add(exppolicy);
                            }
                            AppSettings.ExpirationPolicies = ExpirationPolicies;
                            break;

                        //Collecting MasterPages.
                        case "MasterPages":
                            foreach (XmlElement masterPage in xmlConfigNode.ChildNodes)
                            {
                                ApplyMasterPage MasterPage = new ApplyMasterPage();
                                switch (masterPage.Name)
                                {
                                    case "ApplySystemMasterPage": MasterPage.MasterPageType = MasterPageType.SystemMasterPage;
                                        break;
                                    case "ApplyMasterPage": MasterPage.MasterPageType = MasterPageType.RegularMasterPage;
                                        break;
                                }

                                foreach (XmlAttribute masterPageAttrib in masterPage.Attributes)
                                {
                                    switch (masterPageAttrib.Name)
                                    {
                                        case "Name":
                                            MasterPage.Name = masterPageAttrib.Value;
                                            break;
                                    }
                                }
                                ApplyMasterPages.Add(MasterPage);
                            }

                            AppSettings.ApplyMasterPages = ApplyMasterPages;
                            break;

                        //Collecting ListSettings.
                        case "ListSettings":
                            foreach (XmlElement ListSettingsEntry in xmlConfigNode.ChildNodes)
                            {
                                ListContentTypeManagement ListEntry = new ListContentTypeManagement();
                                ListEntry.Name = ListSettingsEntry.GetAttribute("Name");
                                ListEntry.AllowContentTypeManagement = bool.Parse(ListSettingsEntry.GetAttribute("AllowContentTypeManagement"));
                                ListSettings.Add(ListEntry);
                            }
                            AppSettings.ListSettings = ListSettings;
                            break;

                        //Collecting AuditControl.
                        case "AuditControl":
                            foreach (XmlElement AuditControlEntry in xmlConfigNode.ChildNodes)
                            {
                                switch (AuditControlEntry.Name)
                                {
                                    case "OpeningDownloadingDocuments":
                                        AuditControl.OpeningDownloadingDocuments = bool.Parse(AuditControlEntry.InnerText);
                                        break;
                                    case "EditingItems":
                                        AuditControl.EditingItems = bool.Parse(AuditControlEntry.InnerText);
                                        break;
                                    case "CheckingInOut":
                                        AuditControl.CheckingInOut = bool.Parse(AuditControlEntry.InnerText);
                                        break;
                                    case "MovingCopying":
                                        AuditControl.MovingCopying = bool.Parse(AuditControlEntry.InnerText);
                                        break;
                                    case "DeletingRestoring":
                                        AuditControl.DeletingRestoring = bool.Parse(AuditControlEntry.InnerText);
                                        break;
                                    case "EditingContentTypes":
                                        AuditControl.EditingContentTypes = bool.Parse(AuditControlEntry.InnerText);
                                        break;
                                    case "SearchingSiteContent":
                                        AuditControl.SearchingSiteContent = bool.Parse(AuditControlEntry.InnerText);
                                        break;
                                    case "EditingUsersPermissions":
                                        AuditControl.EditingUsersPermissions = bool.Parse(AuditControlEntry.InnerText);
                                        break;
                                }
                            }
                            AppSettings.AuditControl = AuditControl;
                            break;
                    }
                }
                #endregion

                return AppSettings;
            }
            #endregion

            #region Load SPSite With SDP

            /// <summary>
            /// LoadSettings : This method is invoked/called from "FeatureActivated" a override method to 
            /// Load settings from the "AppConfig.xml" settings for the first time solution activated.
            /// Then it saves backup settings and changes settings on the MOSS/WSS.
            /// This method invokes "InitWeb" method
            /// Then it invokes "LoadSettingsFromAppConfig" method
            /// Then it invokes "LoadExistingAppSettingsFromSPSite" method
            /// Then it invokes "SaveExistingAppSettingsinXML" to Serializing Values to XMLCONFIGFILE
            /// </summary>
            /// <param name="properties"></param>
            public void LoadSPSiteWithSDP(SPFeatureReceiverProperties properties)
            {
                InitWeb(properties);
                AppSettings = LoadSettingsFromAppConfig(properties);
                ExistingAppSettingsBeforeSDP = LoadExistingAppSettingsFromSPSite(properties, site);
                //SaveExistingAppSettingsinXML(properties.Definition.RootDirectory + XMLRETRACTCONFIGFILE, ExistingAppSettingsBeforeSDP);
                ApplySettingstoSPSite(AppSettings, ExistingAppSettingsBeforeSDP, null, true, properties);
            }

            #endregion

            #region Apply Settings to SPSite

            /// <summary>
            /// ApplySettingstoSPSite : This method saves the settings to WSS/MOSS.
            /// The settings are like, ExpirationPolicies, MasterPages, ContentTypes, AuditControl, ListSettings
            /// </summary>
            /// <param name="AppSettings">AppSettingsContainer</param>
            /// <param name="AppSettingsFromXML">AppSettingsContainer</param>
            private void ApplySettingstoSPSite(AppSettingsContainer AppSettings, AppSettingsContainer ExistingAppSettingsBeforeSDP, AppSettingsContainer CurrentAppSettingsBeforeSDP, bool DeployOrRetract, SPFeatureReceiverProperties properties)
            {
                try
                {
                    #region ExpirationPolicies
                     
                    if (AppSettings.ExpirationPolicies != null && DeployOrRetract)
                    {
                        try
                        {
                            foreach (ExpirationPolicy expvar in AppSettings.ExpirationPolicies)
                            {
                                if (expvar.Type == "Site")
                                {
                                    if (site != null)
                                    {
                                        if (site.Url.ToString() == expvar.Name)
                                        {
                                            PolicyCatalog catalog = new PolicyCatalog(site);
                                            PolicyCollection policyList = catalog.PolicyList;
                                            bool NoExpirationPolicy = true;
                                            for (int i = 0; i < policyList.Count; i++)
                                            {
                                                if (policyList[i].Name == expvar.Policy)
                                                {
                                                    NoExpirationPolicy = false;
                                                    break;
                                                }
                                            }
                                            if (NoExpirationPolicy)
                                            {
                                                XmlDocument loadpolicy = new XmlDocument();
                                                loadpolicy.Load(properties.Definition.RootDirectory + @"\ExpirationPolicy\" + expvar.Policy + ".xml");
                                                Policy.ValidateManifest(loadpolicy.OuterXml);
                                                PolicyCollection.Add(site, loadpolicy.OuterXml);
                                            }
                                        }
                                    }
                                }
                            }

                            foreach (ExpirationPolicy expvar in AppSettings.ExpirationPolicies)
                            {
                                if (expvar.Type == "ContentType")
                                {
                                    if (site != null)
                                    {
                                        PolicyCatalog catalog = new PolicyCatalog(site);
                                        PolicyCollection policyList = catalog.PolicyList;
                                        bool ExpirationPolicy = false;
                                        for (int i = 0; i < policyList.Count; i++)
                                        {
                                            if (policyList[i].Name == expvar.Policy)
                                            {
                                                ExpirationPolicy = true;
                                                break;
                                            }
                                        }
                                        if (ExpirationPolicy)
                                        {
                                            if (this.lists[expvar.Name] != null)
                                            {
                                                SPList SpLT = (SPList)this.lists[expvar.Name];
                                                if (SpLT.ContentTypesEnabled)
                                                {
                                                    for (int i = 0; i < SpLT.ContentTypes.Count; i++)
                                                    {
                                                        SPContentType SpCT = SpLT.ContentTypes[i];

                                                        Policy py = policyList[0];
                                                        for (int j = 0; j < policyList.Count; j++)
                                                        {
                                                            if (policyList[j].Name == expvar.Policy)
                                                            {
                                                                py = policyList[j];
                                                            }
                                                        }
                                                        if (Policy.GetPolicy(SpCT) != null)
                                                        {
                                                            if (!SpCT.Sealed)
                                                            {
                                                                Policy.DeletePolicy(SpCT);
                                                                Policy.CreatePolicy(SpCT, py);
                                                            }
                                                        }
                                                        else
                                                        {
                                                            if (!SpCT.Sealed)
                                                            {
                                                                Policy.CreatePolicy(SpCT, py);
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            LogToTempFolder(ex.Message);
                        }
                    }
                    #endregion

                    #region WebTitles
                    if (AppSettings.WebTitles != null && DeployOrRetract)
                    {
                        try
                        {
                            foreach (Title titlename in AppSettings.WebTitles)
                            {
                                if (site != null)
                                {
                                    if (site.Url.ToString() == titlename.Site)
                                    {
                                        web = site.RootWeb;
                                        web.Title = titlename.Name;
                                    }
                                }
                            }
                        }
                        catch (Exception ex)
                        {                            
                            LogToTempFolder(ex.Message.ToString ());
                        }
                    }
                    #endregion

                    #region Apply MasterPages

                    if (AppSettings.ApplyMasterPages != null && DeployOrRetract)
                    {
                        try
                        {
                            foreach (ApplyMasterPage masterPage in AppSettings.ApplyMasterPages)
                            {
                                switch (masterPage.MasterPageType)
                                {
                                    case MasterPageType.SystemMasterPage:
                                        web.CustomMasterUrl = masterPage.Name;
                                        break;

                                    case MasterPageType.RegularMasterPage:
                                        web.MasterUrl = masterPage.Name;
                                        break;
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            LogToTempFolder(ex.Message.ToString());
                        }
                    }
                    else if (AppSettings.ApplyMasterPages != null && !DeployOrRetract)
                    {
                        try
                        {
                           foreach (ApplyMasterPage masterPage in AppSettings.ApplyMasterPages)
                            {
                                switch (masterPage.MasterPageType)
                                {
                                    case MasterPageType.SystemMasterPage:

                                        web.CustomMasterUrl = "/_catalogs/masterpage/default.master";
                                        break;

                                    case MasterPageType.RegularMasterPage:
                                        web.MasterUrl = "/_catalogs/masterpage/default.master";
                                        break;
                                }                            
                            }
                        }
                        catch (Exception ex)
                        {
                            LogToTempFolder(ex.Message.ToString());
                        }
                    }    
                        
                    #endregion

                    #region Apply AuditControl
                   
                    if (AppSettings.AuditControl != null && DeployOrRetract)
                    {
                        try
                        {
                            siteAudit = site.Audit;
                            SPAuditMaskType collectedAuditType = SPAuditMaskType.None;

                            bool InOutWeb, DeletingRestoringWeb, EditingItems, EditingUsersPermissions,
                                  EditingContentTypes, MovingCopying, OpeningDownloadingDocuments, SearchingSiteContent;

                            if (AppSettings.AuditControl.CheckingInOut.HasValue && DeployOrRetract)
                            {
                                collectedAuditType |= AppSettings.AuditControl.CheckingInOut.Value ? SPAuditMaskType.CheckIn | SPAuditMaskType.CheckOut : SPAuditMaskType.None;
                            }
                            if (AppSettings.AuditControl.DeletingRestoring.HasValue && DeployOrRetract)
                            {
                                collectedAuditType |= AppSettings.AuditControl.DeletingRestoring.Value ? SPAuditMaskType.Delete | SPAuditMaskType.Undelete : SPAuditMaskType.None;
                            }
                            if (AppSettings.AuditControl.EditingItems.HasValue && DeployOrRetract)
                            {
                                collectedAuditType |= AppSettings.AuditControl.EditingItems.Value ? SPAuditMaskType.Update : SPAuditMaskType.None;
                            }
                            if (AppSettings.AuditControl.EditingUsersPermissions.HasValue && DeployOrRetract)
                            {
                                collectedAuditType |= AppSettings.AuditControl.EditingUsersPermissions.Value ? SPAuditMaskType.SecurityChange : SPAuditMaskType.None;
                            }
                            if (AppSettings.AuditControl.EditingContentTypes.HasValue && DeployOrRetract)
                            {
                                collectedAuditType |= AppSettings.AuditControl.EditingContentTypes.Value ? SPAuditMaskType.SchemaChange | SPAuditMaskType.ProfileChange : SPAuditMaskType.None;
                            }
                            if (AppSettings.AuditControl.MovingCopying.HasValue && DeployOrRetract)
                            {
                                collectedAuditType |= AppSettings.AuditControl.MovingCopying.Value ? SPAuditMaskType.Move | SPAuditMaskType.Copy : SPAuditMaskType.None;
                            }
                            if (AppSettings.AuditControl.OpeningDownloadingDocuments.HasValue && DeployOrRetract)
                            {
                                collectedAuditType |= AppSettings.AuditControl.OpeningDownloadingDocuments.Value ? SPAuditMaskType.View : SPAuditMaskType.None;
                            }
                            if (AppSettings.AuditControl.SearchingSiteContent.HasValue && DeployOrRetract)
                            {
                                collectedAuditType |= AppSettings.AuditControl.SearchingSiteContent.Value ? SPAuditMaskType.Search : SPAuditMaskType.None;
                            }
                            siteAudit.AuditFlags = collectedAuditType;
                            siteAudit.Update();
                        }
                        catch (Exception ex)
                        {
                            LogToTempFolder(ex.Message.ToString());
                        }
                    }
                    #endregion

                    #region Apply ListSettings
                  
                        if (AppSettings.ListSettings != null && DeployOrRetract)
                        {
                            try
                            {
                                foreach (ListContentTypeManagement list in AppSettings.ListSettings)
                                {

                                    for (int i = 0; i < lists.Count; i++)
                                    {
                                        if (this.lists[i].Title == list.Name)
                                        {
                                            SPList Spl = (SPList)this.lists[list.Name];
                                            Spl.ContentTypesEnabled = list.AllowContentTypeManagement;
                                            Spl.Update();
                                        }
                                    }

                                }
                            }
                            catch (Exception ex)
                            {
                                LogToTempFolder(ex.Message.ToString());
                            }
                        }
                        #region Commented for retract action : Apply ListSettings
                                //else if (ExistingAppSettingsBeforeSDP.ListSettings != null && (!DeployOrRetract))
                                //{
                                //    foreach (ListContentTypeManagement list in ExistingAppSettingsBeforeSDP.ListSettings)
                                //    {
                                //        try
                                //        {
                                //            SPList Spl = (SPList)this.lists[list.Name];
                                //            Spl.ContentTypesEnabled = list.AllowContentTypeManagement;
                                //            Spl.Update();
                                //        }
                                //        catch (Exception ex)
                                //        {
                                //            SPConfigurator.LogToTempFolder(e.Message);
                                //        }
                                //    }                        
                                //}
                                //if (CurrentAppSettingsAfterSDP != null)
                                //{
                                //    if (CurrentAppSettingsAfterSDP.ListSettings != null && (!DeployOrRetract))
                                //    {
                                //        Boolean donothing = false;
                                //        foreach (ListContentTypeManagement currentlist in CurrentAppSettingsAfterSDP.ListSettings)
                                //        {
                                //            foreach (ListContentTypeManagement Appconfiglist in AppSettings.ListSettings)
                                //            {
                                //                if (currentlist.Name == Appconfiglist.Name)
                                //                {
                                //                    donothing = true;
                                //                    break;
                                //                }
                                //                else
                                //                {
                                //                    donothing = false;
                                //                }
                                //            }
                                //            if (!donothing)
                                //            {
                                //                SPList Spl = (SPList)this.lists[currentlist.Name];
                                //                Spl.ContentTypesEnabled = currentlist.AllowContentTypeManagement;
                                //                Spl.Update();
                                //            }
                                //        }
                                //    }
                                //}
                            #endregion
                    #endregion

                    web.Update();
                }
                catch (Exception ex)
                {
                    LogToTempFolder(ex.Message.ToString());
                }
            }

            #endregion

            #region Save Existing AppSettings in XML

            /// <summary>
            /// SaveExistingAppSettingsinXML :  This Method serializes values to XMLCONFIGFILE
            /// </summary>
            /// <param name="filePath">string</param>
            /// <param name="AppSettingsBeforeSDP">AppSettingsContainer</param>
            private void SaveExistingAppSettingsinXML(string filePath, AppSettingsContainer AppSettingsBeforeSDP)
            {
                try
                {
                    BinaryFormatter formatter = new BinaryFormatter();
                    Stream stream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None);
                    formatter.Serialize(stream, AppSettingsBeforeSDP);
                    stream.Close();
                }
                catch (Exception ex)
                {
                    LogToTempFolder(ex.Message.ToString());
                }
            }

            #endregion

            #region Load Settings For Retract

            /// <summary>
            /// LoadSettingsForRetract :  This method Loads Settings For Retract
            /// </summary>
            /// <param name="filePath">string</param>
            /// <returns>AppSettingsContainer</returns>
            public AppSettingsContainer LoadSettingsForRetract(string filePath)
            {
                AppSettingsContainer AppSettingsBeforeSDP = new AppSettingsContainer();
                try
                {                    
                    BinaryFormatter formatter = new BinaryFormatter();
                    Stream stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.None);
                    AppSettingsBeforeSDP = (AppSettingsContainer)formatter.Deserialize(stream);
                    stream.Close();                   
                }
                catch (Exception ex)
                {
                    LogToTempFolder(ex.Message.ToString());
                }
                return AppSettingsBeforeSDP;
            }

            #endregion

            #region Init Web

            /// <summary>
            /// InitWeb :  This method to confirm SPWeb = Publishing Web
            /// </summary>
            /// <param name="properties">SPFeatureReceiverProperties</param>
            private void InitWeb(SPFeatureReceiverProperties properties)
            {
                this.site = properties.Feature.Parent as SPSite;
                this.web = properties.Feature.Parent as SPWeb;            
                try
                {
                    if (site != null)
                    {                        
                        web = site.RootWeb;
                    }
                    this.lists = web.Lists;
                    if (PublishingWeb.IsPublishingWeb(web))
                    {
                        publishingWeb = PublishingWeb.GetPublishingWeb(web);
                    }
                    else
                    {
                        throw new System.ArgumentException("The SPWeb must be a PublishingWeb", "web");
                    }
                }
                catch (Exception ex)
                {
                    LogToTempFolder(ex.Message.ToString());
                }               
            }

            #endregion

            #region Retract Settings

            /// <summary>
            /// RetractSettings :  This method Loads backup settings from the AppConfig settings and then changes settings on the MOSS/WSS.
            /// This method invokes the "LoadSettingsForRetract" method
            /// This method then invokes the "LoadSettingsFromAppConfig" method
            /// This method then it invokes the "ApplySettingstoSPSite" method
            /// </summary>
            /// <param name="properties"></param>
            public void RetractSettings(SPFeatureReceiverProperties properties)
            {
                InitWeb(properties);
                AppSettings = LoadSettingsFromAppConfig(properties);
                AppSettingsContainer ExistingAppSettingsBeforeSDP = LoadSettingsForRetract(properties.Definition.RootDirectory + AppSettingsModifier.XMLRETRACTCONFIGFILE);
                //CurrentAppSettingsAfterSDP = LoadCurrentAppSettingsFromSPSite(properties, site);
                //SaveExistingAppSettingsinXML(properties.Definition.RootDirectory + XMLRETRACTCONFIGFILE, ExistingAppSettingsBeforeSDP);                
                ApplySettingstoSPSite(AppSettings, ExistingAppSettingsBeforeSDP, null, false, properties);
            }

            #endregion

            #region Data Construction

            [Serializable]
            public class AppSettingsContainer
            {
                public List<ExpirationPolicy> ExpirationPolicies;
                public List<ApplyMasterPage> ApplyMasterPages;
                public AuditControls AuditControl;
                public List<ListContentTypeManagement> ListSettings;
                public List<ContentType> ContentTypes;
                public List<Title> WebTitles;
            }

            [Serializable]
            public struct ExpirationPolicy
            {
                public string Type;
                public string Name;
                public string Policy;
            }

            [Serializable]
            public struct ApplyMasterPage
            {
                public string Name;
                public MasterPageType MasterPageType;
            }

            [Serializable]
            public enum MasterPageType
            {
                SystemMasterPage,
                RegularMasterPage
            }

            [Serializable]
            public struct ContentType
            {
                public string Name;
                public string Policy;
            }

            [Serializable]
            public class AuditControls
            {
                public bool? OpeningDownloadingDocuments;
                public bool? EditingItems;
                public bool? CheckingInOut;
                public bool? MovingCopying;
                public bool? DeletingRestoring;
                public bool? EditingContentTypes;
                public bool? SearchingSiteContent;
                public bool? EditingUsersPermissions;
            }

            [Serializable]
            public struct ListContentTypeManagement
            {
                public string Name;
                public bool AllowContentTypeManagement;
            }

            [Serializable]
            public struct Title
            {
                public string Site;
                public string Name;
            }
            #endregion
        }
    }
    #endregion
}
#endregion
